import { Grid } from "../../lib/kgame/d2/Grid";
import { QuadTree } from "../../lib/kgame/d2/QuadTree";
import { Rect } from "../../lib/kgame/d2/math/Rect";
import { Vec2 } from "../../lib/kgame/d2/math/Vec2";
import { ECSSceneCmp } from "../../lib/kgame/ecs/ECSSceneCmp";
import { ArrUtil } from "../../lib/kgame/util/ArrUtil";
import { IRect, IVec2 } from "../../lib/kgame/util/Defined";
import { CmpChunkEntity } from "../cmp/CmpChunkEntity";
import { CmpFood } from "../cmp/CmpFood";
import { CmpSnakeBody } from "../cmp/CmpSnakeBody";

const TPOS = new Vec2();

/**
 * 世界管理
 */
export class SCmpWorld extends ECSSceneCmp {

    /** 世界大小 */
    rect: Rect;
    /** 区块 */
    chunk: Grid<CmpChunkEntity>;
    /** 蛇身四叉树 */
    snakeQuadTree: QuadTree<CmpSnakeBody>;
    /** 食物网格 */
    foodGrid: Grid<CmpFood>;
    /** 被吃的食物 */
    eatenFoods: kp_entity_eatenFood[] = [];
    /** 当前蛇唯一id最大值 */
    curSnakeId: number = 0;
    /** ai随机名池 */
    aiSnakeNamePool: [number, number][] = [];

    constructor(
        /** 世界宽度 */
        width: number,
        /** 世界高度 */
        height: number,
        /** 最大食物数量 */
        public foodMax: number
    ) {
        super();
        const chunkCol = Math.ceil(width / 10);
        const chunkRow = Math.ceil(height / 10);
        this.rect = new Rect(-width / 2, -height / 2, width, height);
        this.chunk = new Grid(this.rect, chunkCol, chunkRow);
        this.snakeQuadTree = new QuadTree(this.rect, 20, 5);
        this.foodGrid = new Grid(this.rect, 10, 10);
    }

    onAdd(): void {
        let aiId = 1;
        while (aiId < 999) {
            const cur = aiId;
            aiId = Math.min(999, cur + this.scene.rand.range(10, 50) >> 0);
            this.aiSnakeNamePool.push([cur, aiId]);
        }
    }

    onRemove(): void {
        this.chunk.clear();
    }

    /**
     * 获取一个唯一的蛇id
     */
    getSnakeId() {
        return ++this.curSnakeId;
    }

    /**
     * 获取一个不重复的随机AI名
     */
    getAIName() {
        const { rand } = this.scene;
        const range = rand.choose(this.aiSnakeNamePool);
        const name = "AI" + range[0];
        if (++range[0] > range[1]) {
            ArrUtil.remove(this.aiSnakeNamePool, range);
        }
        return name;
    }

    /**
     * 获取随机位置
     * @param safeDis 安全距离
     * @param out 输出点
     */
    getRandPos<T extends IVec2 = Vec2>(safeDis = 0, out: T = TPOS as any) {
        return Vec2.setPos(out,
            this.rect.x + this.scene.rand.range(safeDis, this.rect.width - safeDis),
            this.rect.y + this.scene.rand.range(safeDis, this.rect.height - safeDis)
        )
    }

    /**
     * 包围盒是否超出边界了
     * @param aabb
     */
    isOutEdge(aabb: IRect) {
        return !this.rect.containsRect(aabb);
    }

}